categories/[slug]/page.tsx - 分类详情页
基本信息
| 属性 | 值 |
| 路径 | src/app/categories/[slug]/page.tsx |
| 类型 | Next.js 动态路由页面 (Server Component) |
| 功能 | 显示特定分类下的提示词列表 |
功能描述
展示单个分类的详细信息,包括分类描述、提示词数量、订阅功能,以及该分类下的提示词列表。支持分页、排序和搜索。
导入依赖
import { Metadata } from "next";
import { notFound } from "next/navigation";
import Link from "next/link";
import { getTranslations } from "next-intl/server";
import { ArrowLeft } from "lucide-react";
import { auth } from "@/lib/auth";
import { db } from "@/lib/db";
import config from "@/../prompts.config";
import { Button } from "@/components/ui/button";
import { PromptList } from "@/components/prompts/prompt-list";
import { SubscribeButton } from "@/components/categories/subscribe-button";
import { CategoryFilters } from "@/components/categories/category-filters";
import { McpServerPopup } from "@/components/mcp/mcp-server-popup";
Props 接口
interface CategoryPageProps {
params: Promise<{ slug: string }>;
searchParams: Promise<{ page?: string; sort?: string; q?: string }>;
}
| 参数 | 类型 | 说明 |
params.slug | string | 分类的 URL slug |
searchParams.page | string | 分页页码 |
searchParams.sort | string | 排序方式 |
searchParams.q | string | 搜索关键词 |
常量
const PROMPTS_PER_PAGE = 30;
元数据生成
{
title: category.name,
description: category.description || `Browse prompts in ${category.name}`
}
查询参数处理
| 参数 | 默认值 | 处理 |
page | 1 | Math.max(1, parseInt(...)) |
sort | "newest" | 直接使用 |
q | - | 可选搜索词 |
排序选项
| 选项值 | 排序逻辑 |
oldest | createdAt: "asc" |
most_upvoted | votes._count: "desc" |
most_contributors | contributors._count: "desc" |
| 默认 | createdAt: "desc" |
数据查询
分类查询
const category = await db.category.findUnique({
where: { slug },
include: {
_count: {
select: { prompts: true, subscribers: true }
}
}
});
订阅状态
const isSubscribed = session?.user
? await db.categorySubscription.findUnique({
where: {
userId_categoryId: {
userId: session.user.id,
categoryId: category.id
}
}
})
: null;
提示词查询条件
const whereClause = {
categoryId: category.id,
isPrivate: false,
isUnlisted: false,
deletedAt: null,
...(q && {
OR: [
{ title: { contains: q, mode: "insensitive" } },
{ content: { contains: q, mode: "insensitive" } }
]
})
};
UI 结构
Container
└── Header
├── Back Button → /categories
├── Title Row
│ ├── Category Name
│ ├── SubscribeButton (if logged in)
│ └── Description
├── Stats Row
│ ├── Prompt Count
│ └── Subscriber Count
└── Filters (desktop + mobile)
├── CategoryFilters
└── McpServerPopup
└── PromptList
└── prompts + pagination
响应式布局
| 断点 | 过滤器位置 |
Desktop (md:) | 标题右侧 |
| Mobile | 统计信息下方 |
翻译键值
| 键值 | 用途 |
categories.allCategories | 返回按钮 |
categories.promptCount | 提示词数量 |
categories.subscriberCount | 订阅者数量 |
组件引用
| 组件 | 用途 |
PromptList | 提示词列表 + 分页 |
SubscribeButton | 订阅/取消订阅 |
CategoryFilters | 排序筛选器 |
McpServerPopup | MCP 服务器配置 |
路由
| 路径 | 说明 |
/categories | 返回分类列表 |
/categories/${slug} | 当前页 |
MCP 集成
当 config.features.mcp !== false 时显示 MCP 服务器弹窗,预填充当前分类。